package com.srmt.common.ratelimit.config;

import java.util.Map;
import java.util.Properties;
import java.util.concurrent.ConcurrentHashMap;

/**
 * 限流配置类
 * 管理全局限流配置和各API的个性化配置
 * 
 * @author SRMT Development Team
 * @since 1.0.0
 */
public class RateLimitConfig {
    
    /**
     * 是否启用限流
     * 使用volatile保证可见性
     */
    private volatile boolean enabled = true;
    
    /**
     * 默认QPS限制
     * 使用volatile保证可见性
     */
    private volatile int defaultQps = 20;
    
    /**
     * 默认重试超时时间(毫秒)
     * 使用volatile保证可见性
     */
    private volatile long defaultRetryTimeout = 5000;
    
    /**
     * 默认最大重试次数
     * 使用volatile保证可见性
     */
    private volatile int defaultMaxRetries = 3;
    
    /**
     * 各API的个性化配置
     * 使用ConcurrentHashMap保证线程安全
     */
    private final Map<String, ApiConfig> apiConfigs = new ConcurrentHashMap<>();
    
    /**
     * 扩展属性（用于自定义限流器）
     * 使用ConcurrentHashMap保证线程安全
     */
    private final Map<String, String> properties = new ConcurrentHashMap<>();

    /**
     * 自定义限流器实现（可选）
     * 用于分布式限流场景，如基于Redis的限流器
     * 如果设置，将优先使用此限流器而非默认实现
     */
    private com.srmt.common.ratelimit.RateLimiter customRateLimiter;

    /**
     * API级别的配置
     * 所有字段使用volatile保证多线程可见性
     */
    public static class ApiConfig {
        private volatile int qps;
        private volatile long retryTimeout;
        private volatile int maxRetries;
        private volatile boolean enabled = true;
        
        public ApiConfig() {
        }
        
        public ApiConfig(int qps) {
            this.qps = qps;
        }
        
        public ApiConfig(int qps, long retryTimeout, int maxRetries) {
            this.qps = qps;
            this.retryTimeout = retryTimeout;
            this.maxRetries = maxRetries;
        }
        
        // Getters and Setters
        public int getQps() {
            return qps;
        }
        
        public void setQps(int qps) {
            this.qps = qps;
        }
        
        public long getRetryTimeout() {
            return retryTimeout;
        }
        
        public void setRetryTimeout(long retryTimeout) {
            this.retryTimeout = retryTimeout;
        }
        
        public int getMaxRetries() {
            return maxRetries;
        }
        
        public void setMaxRetries(int maxRetries) {
            this.maxRetries = maxRetries;
        }
        
        public boolean isEnabled() {
            return enabled;
        }
        
        public void setEnabled(boolean enabled) {
            this.enabled = enabled;
        }
    }
    
    /**
     * 从Properties加载配置
     */
    public static RateLimitConfig fromProperties(Properties props) {
        RateLimitConfig config = new RateLimitConfig();
        
        // 全局配置
        if (props.containsKey("rate.limit.enabled")) {
            config.setEnabled(Boolean.parseBoolean(props.getProperty("rate.limit.enabled")));
        }
        
        
        if (props.containsKey("rate.limit.default.qps")) {
            config.setDefaultQps(Integer.parseInt(props.getProperty("rate.limit.default.qps")));
        }
        
        if (props.containsKey("rate.limit.default.retry.timeout")) {
            config.setDefaultRetryTimeout(Long.parseLong(props.getProperty("rate.limit.default.retry.timeout")));
        }
        
        if (props.containsKey("rate.limit.default.max.retries")) {
            config.setDefaultMaxRetries(Integer.parseInt(props.getProperty("rate.limit.default.max.retries")));
        }
        
        // API级别配置
        for (String key : props.stringPropertyNames()) {
            if (key.startsWith("rate.limit.api.") && key.endsWith(".qps")) {
                String apiName = key.substring("rate.limit.api.".length(), key.length() - ".qps".length());
                int qps = Integer.parseInt(props.getProperty(key));
                
                ApiConfig apiConfig = config.getApiConfig(apiName);
                apiConfig.setQps(qps);
                
                // 查找对应的重试配置
                String retryTimeoutKey = "rate.limit.api." + apiName + ".retry.timeout";
                if (props.containsKey(retryTimeoutKey)) {
                    apiConfig.setRetryTimeout(Long.parseLong(props.getProperty(retryTimeoutKey)));
                } else {
                    apiConfig.setRetryTimeout(config.getDefaultRetryTimeout());
                }
                
                String maxRetriesKey = "rate.limit.api." + apiName + ".max.retries";
                if (props.containsKey(maxRetriesKey)) {
                    apiConfig.setMaxRetries(Integer.parseInt(props.getProperty(maxRetriesKey)));
                } else {
                    apiConfig.setMaxRetries(config.getDefaultMaxRetries());
                }
                
                config.setApiConfig(apiName, apiConfig);
            }
            
            // 扩展属性（如Redis配置）
            if (key.startsWith("rate.limit.") && !key.startsWith("rate.limit.api.") 
                && !key.startsWith("rate.limit.default.") && !key.equals("rate.limit.enabled")) {
                String propKey = key.substring("rate.limit.".length());
                config.setProperty(propKey, props.getProperty(key));
            }
        }
        
        return config;
    }
    
    /**
     * 获取API配置，如果不存在则返回默认配置
     */
    public ApiConfig getApiConfig(String api) {
        return apiConfigs.computeIfAbsent(api, k -> {
            ApiConfig config = new ApiConfig();
            config.setQps(defaultQps);
            config.setRetryTimeout(defaultRetryTimeout);
            config.setMaxRetries(defaultMaxRetries);
            return config;
        });
    }
    
    /**
     * 设置API配置
     */
    public void setApiConfig(String api, ApiConfig config) {
        apiConfigs.put(api, config);
    }
    
    /**
     * 设置API的QPS
     */
    public void setApiQps(String api, int qps) {
        getApiConfig(api).setQps(qps);
    }
    
    /**
     * 获取API的QPS限制
     */
    public int getApiQps(String api) {
        ApiConfig config = apiConfigs.get(api);
        return config != null ? config.getQps() : defaultQps;
    }
    
    /**
     * 获取API的重试超时时间
     */
    public long getApiRetryTimeout(String api) {
        ApiConfig config = apiConfigs.get(api);
        return config != null ? config.getRetryTimeout() : defaultRetryTimeout;
    }
    
    /**
     * 获取API的最大重试次数
     */
    public int getApiMaxRetries(String api) {
        ApiConfig config = apiConfigs.get(api);
        return config != null ? config.getMaxRetries() : defaultMaxRetries;
    }
    
    // Getters and Setters
    public boolean isEnabled() {
        return enabled;
    }
    
    public void setEnabled(boolean enabled) {
        this.enabled = enabled;
    }
    
    public int getDefaultQps() {
        return defaultQps;
    }
    
    public void setDefaultQps(int defaultQps) {
        this.defaultQps = defaultQps;
    }
    
    public long getDefaultRetryTimeout() {
        return defaultRetryTimeout;
    }
    
    public void setDefaultRetryTimeout(long defaultRetryTimeout) {
        this.defaultRetryTimeout = defaultRetryTimeout;
    }
    
    public int getDefaultMaxRetries() {
        return defaultMaxRetries;
    }
    
    public void setDefaultMaxRetries(int defaultMaxRetries) {
        this.defaultMaxRetries = defaultMaxRetries;
    }
    
    public Map<String, ApiConfig> getApiConfigs() {
        return apiConfigs;
    }
    
    public void setApiConfigs(Map<String, ApiConfig> apiConfigs) {
        this.apiConfigs.clear();
        this.apiConfigs.putAll(apiConfigs);
    }
    
    public Map<String, String> getProperties() {
        return properties;
    }
    
    public void setProperties(Map<String, String> properties) {
        this.properties.clear();
        this.properties.putAll(properties);
    }
    
    public void setProperty(String key, String value) {
        this.properties.put(key, value);
    }
    
    public String getProperty(String key) {
        return this.properties.get(key);
    }

    public com.srmt.common.ratelimit.RateLimiter getCustomRateLimiter() {
        return customRateLimiter;
    }

    public void setCustomRateLimiter(com.srmt.common.ratelimit.RateLimiter customRateLimiter) {
        this.customRateLimiter = customRateLimiter;
    }

    /**
     * 创建Builder实例
     */
    public static Builder builder() {
        return new Builder();
    }
    
    /**
     * Builder类，用于构建RateLimitConfig
     */
    public static class Builder {
        private boolean enabled = true;
        private int defaultQps = 20;
        private long defaultRetryTimeout = 5000;
        private int defaultMaxRetries = 3;
        private Map<String, ApiConfig> apiConfigs = new ConcurrentHashMap<>();
        private Map<String, String> properties = new ConcurrentHashMap<>();
        private com.srmt.common.ratelimit.RateLimiter customRateLimiter;

        public Builder enabled(boolean enabled) {
            this.enabled = enabled;
            return this;
        }
        
        public Builder defaultQps(int defaultQps) {
            this.defaultQps = defaultQps;
            return this;
        }
        
        public Builder defaultRetryTimeout(long defaultRetryTimeout) {
            this.defaultRetryTimeout = defaultRetryTimeout;
            return this;
        }
        
        public Builder defaultMaxRetries(int defaultMaxRetries) {
            this.defaultMaxRetries = defaultMaxRetries;
            return this;
        }
        
        public Builder apiConfig(String api, ApiConfig config) {
            this.apiConfigs.put(api, config);
            return this;
        }
        
        public Builder property(String key, String value) {
            this.properties.put(key, value);
            return this;
        }

        public Builder customRateLimiter(com.srmt.common.ratelimit.RateLimiter customRateLimiter) {
            this.customRateLimiter = customRateLimiter;
            return this;
        }

        public RateLimitConfig build() {
            RateLimitConfig config = new RateLimitConfig();
            config.enabled = this.enabled;
            config.defaultQps = this.defaultQps;
            config.defaultRetryTimeout = this.defaultRetryTimeout;
            config.defaultMaxRetries = this.defaultMaxRetries;
            config.apiConfigs.putAll(this.apiConfigs);
            config.properties.putAll(this.properties);
            config.customRateLimiter = this.customRateLimiter;
            return config;
        }
    }
}